///在面向对象的编程语言中，mixin（或mix-in）是一个类，其中包含供其他类使用的方法，而不必成为其他类的父类。
///这些其他类如何获得对mixin方法的访问权限取决于语言。 混合素有时被描述为“包含”而不是“继承”。
///Mixins鼓励代码重用，并且可用于避免多重继承可能导致的继承歧义（“钻石问题”），或解决语言中对多重继承的支持不足的问题。
///混合也可以看作是已实现方法的接口。 此模式是强制执行依赖关系反转原理的示例。
//

class Person {
  eat() {
    print('Person eat');
  }
}

mixin Dance {
  dance() {
    print('Dance dance');
  }
}

mixin Sing {
  sing() {
    print('Sing sing');
  }
}

mixin Code on Person {
  code() {
    print('Code code');
  }
}

class A extends Person with Dance, Sing {}

class B extends Person with Sing, Code {}

class C extends Person with Code, Dance {}

test() {
  A a = A();
  a.eat();
  a.dance();
  a.sing();
}

////////////////////////////////////////////////////////////////////////////////
class TestC extends Person with Code, Dance {
  //error
  dance() {}
}

///添加限定条件，使用关键字 on
///使用关键字 on 限定Code 只能被 Person 或者其子类 mixin
class TestD extends Person with Code {}

///如何处理多个类有同一方法的情况 -> 将前面的覆盖了
///混合类时，进行混合的多个类是线性的，这是他们共有方法不冲突的原因，混合的顺序非常重要，因为它决定了混合时相同的方法的处理逻辑。

////////////////////////////////////////////////////////////////////////////////
abstract class AB {
  AB() {
    print("AB Constructor");
    init();
  }

  init() {
    print("AB init");
  }
}

mixin AC on AB {
  @override
  init() {
    super.init();
    print("AC init");
  }
}

mixin AD on AB {
  @override
  init() {
    super.init();
    print("AD init");
  }
}

class ABCD extends AB with AC, AD {}

test4() {
  ABCD().init();
//  flutter: AB Constructor
//  flutter: AD init
//  flutter: AC init
//  flutter: AB init
}

////////////////////////////////////////////////////////////////////////////////
///Mixins 使我们可以在无需继承父类的情况下为此类添加父类的“功能”，可以在同一个类中具有一个父级和多个 mixin 组件。
///Mixins 不可以声明任何构造函数。
///给 Mixins 添加限定条件使用 on 关键字。
///混合使用 with 关键字，with 后面可以是 class、abstract class 和 mixin 的类型。
///Mixins 不是多重继承，相反，它只是在多个层次结构中重用类中的代码而无需扩展它们的一种方式。
main() {
  test();
  test4();
}
